/******************************************************************************
*@file  : app.c
*@brief : UART Demos 
******************************************************************************/
#include "app.h"

UART_HandleTypeDef  UART1_Handle;
UART_HandleTypeDef  UART2_Handle;

uint8_t  test_data_buf[256]={0x20,0x09,0x0d,0x31,0x2e,0x2e,0x42,0x17,0x93,0xfa,0xeb,0x68,0x1d,0x0b,0x50,0xe4,0xe1,0xca,0x8a,0xd9,0x58,0x58,0xcf,0x4e,0xd6,0x06,0x77,0x48,0x81,0xd6,0x7c,0xa1,
0xd6,0xf8,0xbf,0xa5,0x5a,0xa6,0x7e,0xc2,0x4c,0x0f,0xaa,0x34,0xd6,0x50,0xa7,0x18,0xe1,0x12,0x8c,0xe6,0xc1,0xf3,0x7b,0xb1,0x20,0xc9,0x1b,0x4a,0x4f,0x96,0xab,0xfd,
0x70,0x41,0xcf,0x9a,0xb3,0x47,0x09,0x1f,0x26,0x25,0x5d,0xd7,0x12,0x5e,0x25,0x3b,0x5d,0x09,0x40,0xa3,0x21,0x43,0x9f,0x35,0xf9,0x61,0x48,0x1f,0xb3,0x34,0xcd,0xc5,
0xff,0x62,0xa0,0x71,0x19,0x8e,0x95,0x6f,0x7d,0x2a,0x37,0x0a,0x5c,0x4a,0x83,0x4b,0x29,0x87,0x33,0xf7,0x11,0xe4,0x22,0x9d,0x63,0xf5,0xec,0x4b,0xc6,0x32,0x56,0xc1,
0x59,0x6a,0x25,0x2f,0x97,0x54,0x85,0x99,0x6c,0x6e,0x97,0xc9,0xd6,0x95,0x01,0x8e,0x49,0x7f,0xd3,0x35,0xde,0x59,0x11,0xea,0x6a,0xf3,0x7a,0xbb,0xb5,0x2a,0xa1,0x79,
0x54,0xf8,0xfd,0x22,0xa8,0xc7,0xbc,0xf0,0x8c,0xf4,0xdc,0xa0,0x40,0x08,0xf3,0xd1,0x07,0xc2,0x11,0xd4,0x4f,0x2e,0xa0,0xed,0xc2,0xa8,0x7c,0xf6,0x53,0x81,0x5d,0x1f,
0x0e,0x39,0x77,0x73,0x21,0x57,0x67,0x63,0xaa,0xa9,0xfd,0xa5,0xec,0xaf,0x7f,0x7a,0x04,0x8c,0x1c,0xba,0x4d,0xc6,0x64,0xce,0xe5,0x3b,0x8a,0x37,0x8e,0xdd,0x44,0x16,
0x26,0x6f,0xec,0xa1,0x96,0x29,0x30,0x55,0x30,0x9d,0x36,0x2d,0xef,0x5a,0xfc,0x50,0xd6,0x5e,0xaf,0x4e,0x60,0x56,0x3c,0xae,0x4a,0x31,0x9a,0xe7,0x97,0x64,0xd8,0x44};
uint16_t test_data_buf_16[128];
uint32_t test_data_buf_32[64];

void test_data_init(void)
{
	uint32_t i;
	for(i = 0; i < 256; i++ )
	{
		test_data_buf[i] = i;
	}
}

uint16_t CRC16_base_MSB(uint16_t crc,uint8_t data, uint16_t poly)
{
	uint8_t i;

	crc = crc ^ (uint16_t)(data <<8);
	for(i=0;i<8;i++)
	{
		if((crc&0x8000) == 0x8000)
		{
			crc = (crc << 1) ^ poly;
		}
		else
		{
			crc = crc << 1;
		}
	}
	return crc&0xffff;
}

uint16_t CRC16_soft_MSB(uint8_t crc_data[], uint32_t len, uint16_t poly, uint16_t init_data, uint16_t result_xor)
{
	uint32_t i;
	uint16_t reg_crc;

	reg_crc = init_data;

	for( i = 0; i < len; i++ )
	{
		reg_crc = CRC16_base_MSB(reg_crc,crc_data[i],poly);	
	}
	return (reg_crc^result_xor)&0xffff;
}



/******************************************************************************
*@brief : APP_CRC16_Test
*@param : none
*@return: none
******************************************************************************/
void APP_CRC16_Test(void)
{
	uint32_t result1,result2;
	uint32_t poly,init,xor_out;
	uint32_t byte_len;

	CRC_HandleTypeDef handle_crc;

	test_data_init();
	byte_len = 256;
	
	poly = 0x1021;  //poly = x16+x12+x5+1
	init = 0xFFFF;
	xor_out = 0x0000;
	
	result1 = CRC16_soft_MSB(test_data_buf,byte_len,poly,init,xor_out);	//comput by software
	
	handle_crc.Instance = CRC;
	handle_crc.Init.PolyRev = CRC_POLY_REV_EN;      //need to be fixed to REV_EN
	handle_crc.Init.OutxorRev = CRC_OUTXOR_REV_EN;  //need to be fixed to REV_EN
	handle_crc.Init.InitRev = CRC_INIT_REV_EN;      //need to be fixed to REV_EN
	handle_crc.Init.RsltRev = CRC_RSLT_REV_EN;      //opposite to common CRC tools 
	handle_crc.Init.DataRev = CRC_DATA_REV_BY_BYTE; //opposite to common CRC tools
	handle_crc.Init.PolyLen = CRC_POLTY_LEN_16;
	handle_crc.Init.DataLen = CRC_DATA_LEN_1B;
	
	handle_crc.Init.PolyData = 0x1021;  //poly = x16+x12+x5+1(CRC-16/CCIT-FALSE)
	handle_crc.Init.InitData = 0xFFFF;
	handle_crc.Init.OutXorData = 0x0000;
	
	handle_crc.CRC_Data_Buff = test_data_buf;
	handle_crc.CRC_Data_Len = byte_len;
	
    HAL_CRC_Init(&handle_crc);

//	result2 = HAL_CRC_Calculate(&handle_crc); //comput by hardware

	handle_crc.CRC_Data_Buff = test_data_buf;
	handle_crc.CRC_Data_Len = byte_len/2;
    result2 = HAL_CRC_Calculate(&handle_crc); //comput by hardware
    
	handle_crc.CRC_Data_Buff = test_data_buf+byte_len/2;
	handle_crc.CRC_Data_Len = byte_len/2;
    result2 = HAL_CRC_Calculate(&handle_crc); //comput by hardware

	printf("\nresult1(soft)   = 0x%x\n", result1);
	printf("result2(normal) = 0x%x\n", result2);
	
	if (result1 == result2)
	{
		printf("\nCRC-16 test success\n");
	} 
	else
	{
		printf("CRC-16 test fail\n");
	}			

}

uint32_t crc32_base_MSB(uint32_t crc, uint8_t data, uint32_t poly)
{
	uint8_t i;

	crc = crc ^ (int)data << 24;
	for(i = 0; i < 8; i++)
	{
		if((crc & 0x80000000) == 0x80000000)
		{
			crc = crc << 1 ^ poly;
		}
		else
		{
			crc = crc << 1;
		}
	}
	return crc;
}

uint32_t CRC32_soft_MSB(uint8_t crc_data[], uint32_t len, uint32_t poly, uint32_t init_data, uint32_t result_xor)
{
	uint32_t i;
	uint32_t reg_crc;

	reg_crc = init_data;

	for( i = 0; i < len; i++ )
	{
		reg_crc = crc32_base_MSB(reg_crc,crc_data[i],poly);	
	}
	return (reg_crc ^ result_xor);
}

/******************************************************************************
*@brief : APP_CRC32_Test
*@param : none
*@return: none
******************************************************************************/
void APP_CRC32_Test(void)
{
    int i;
	uint32_t result1,result2,result3,result4;
	uint32_t poly,init,xor_out;
	uint32_t byte_len;
    uint16_t test_data_buf_16[128];
    uint32_t test_data_buf_32[64];

	CRC_HandleTypeDef handle_crc;

	test_data_init();
	byte_len = 256;
    
 	poly = 0x04C11DB7;  //CRC32/MPEG-2 : poly = x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 +x + 1
	init = 0xFFFFFFFF;
	xor_out = 0x00000000;
	
	/* input DataLen = 1 bytes             *
	 * indata: 0x00, 0x01, 0x02, ..., 0xFF */
	result1 = CRC32_soft_MSB(test_data_buf,byte_len,poly,init,xor_out);	//comput by software
	printf("\nresult1(soft)             = 0x%x\n", result1);
	
	handle_crc.Instance = CRC;
	handle_crc.Init.PolyRev = CRC_POLY_REV_EN;      //need to be fixed to REV_EN
	handle_crc.Init.OutxorRev = CRC_OUTXOR_REV_EN;  //need to be fixed to REV_EN
	handle_crc.Init.InitRev = CRC_INIT_REV_EN;      //need to be fixed to REV_EN
	handle_crc.Init.RsltRev = CRC_RSLT_REV_EN;      //opposite to common CRC tools 
	handle_crc.Init.DataRev = CRC_DATA_REV_BY_BYTE; //opposite to common CRC tools
	handle_crc.Init.PolyLen = CRC_POLTY_LEN_32;
	handle_crc.Init.DataLen = CRC_DATA_LEN_1B;
	
	handle_crc.Init.PolyData = 0x04C11DB7;  //CRC32/MPEG-2 : poly = x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 +x + 1
	handle_crc.Init.InitData = 0xFFFFFFFF;
	handle_crc.Init.OutXorData = 0x00000000;    
	
	handle_crc.CRC_Data_Buff = test_data_buf;
	handle_crc.CRC_Data_Len = byte_len;
	
    HAL_CRC_Init(&handle_crc);

	result2 = HAL_CRC_Calculate(&handle_crc); //comput by hardware

//	handle_crc.CRC_Data_Buff = test_data_buf;
//	handle_crc.CRC_Data_Len = byte_len/2;
//  result2 = HAL_CRC_Calculate(&handle_crc); //comput by hardware
//    
//	handle_crc.CRC_Data_Buff = test_data_buf+byte_len/2;
//	handle_crc.CRC_Data_Len = byte_len/2;
//  result2 = HAL_CRC_Calculate(&handle_crc); //comput by hardware
    
	printf("result2(normal)           = 0x%x\n", result2);
	
	/* input DataLen = 2 bytes                     *
	 * indata: 0x0001, 0x0203, 0x0405, ..., 0xFEFF */
    for(i = 0; i < 128; i++ )
	{
	    test_data_buf_16[i] = ((i*2)<<8) | (i*2 + 1);
    }    	

	handle_crc.Instance = CRC;
	handle_crc.Init.PolyRev = CRC_POLY_REV_EN;      //need to be fixed to REV_EN
	handle_crc.Init.OutxorRev = CRC_OUTXOR_REV_EN;  //need to be fixed to REV_EN
	handle_crc.Init.InitRev = CRC_INIT_REV_EN;      //need to be fixed to REV_EN
	handle_crc.Init.RsltRev = CRC_RSLT_REV_EN;      //opposite to common CRC tools 
	handle_crc.Init.DataRev = CRC_DATA_REV_BY_HALFWORD; //opposite to common CRC tools
	handle_crc.Init.PolyLen = CRC_POLTY_LEN_32;
	handle_crc.Init.DataLen = CRC_DATA_LEN_2B;
	
	handle_crc.Init.PolyData = 0x04C11DB7;  //CRC32/MPEG-2 : poly = x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 +x + 1
	handle_crc.Init.InitData = 0xFFFFFFFF;
	handle_crc.Init.OutXorData = 0x00000000;    
    HAL_CRC_Init(&handle_crc);
    
    handle_crc.CRC_Data_Buff = test_data_buf_16;
	handle_crc.CRC_Data_Len = sizeof(test_data_buf_16);

	result3 = HAL_CRC_Calculate(&handle_crc); //comput by hardware
	printf("result3(DataLen = 2bytes) = 0x%x\n", result3);

	/* input DataLen = 4 bytes                                     *
	 * indata: 0x00010203, 0x04050607, 0x08090A0B, ..., 0xFCFDFEFF */
	for(i = 0; i < 64; i++ )
	{
		test_data_buf_32[i] = ((i*4)<<24) | ((i*4+1)<<16) | ((i*4+2)<<8) | (i*4 + 3);
	}    

	handle_crc.Instance = CRC;
	handle_crc.Init.PolyRev   = CRC_POLY_REV_EN;    //need to be fixed to REV_EN
	handle_crc.Init.OutxorRev = CRC_OUTXOR_REV_EN;  //need to be fixed to REV_EN
	handle_crc.Init.InitRev = CRC_INIT_REV_EN;      //need to be fixed to REV_EN
	handle_crc.Init.RsltRev = CRC_RSLT_REV_EN;      //opposite to common CRC tools 
	handle_crc.Init.DataRev = CRC_DATA_REV_BY_WORD; //opposite to common CRC tools
	handle_crc.Init.PolyLen = CRC_POLTY_LEN_32;
	handle_crc.Init.DataLen = CRC_DATA_LEN_4B;
	
	handle_crc.Init.PolyData = 0x04C11DB7;  //CRC32/MPEG-2 : poly = x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 +x + 1
	handle_crc.Init.InitData = 0xFFFFFFFF;
	handle_crc.Init.OutXorData = 0x00000000;    
    HAL_CRC_Init(&handle_crc);
    
    handle_crc.CRC_Data_Buff = test_data_buf_32;
	handle_crc.CRC_Data_Len = sizeof(test_data_buf_32);

	result4 = HAL_CRC_Calculate(&handle_crc); //comput by hardware
	printf("result4(DataLen = 4bytes) = 0x%x\n", result4);
    
	if ((result1 == result2)&&(result2 == result3)&&(result3 == result4))
	{
		printf("\nCRC-32 test success\n");
	} 
	else
	{
		printf("CRC-32 test fail\n");
	}

}
